﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataMgr.File
{
    /// <summary>
    /// bdf记录数据读取
    /// </summary>
    class FileRecordsRead
    {
        private FileStream m_file = null;
        private UInt32 m_dwRecordSize = 0;      //一条记录占用的字节大小
        private UInt32 m_dwRecordTotal = 0;     //文件记录的总个数
        private UInt32 m_dwCurIndex = 0;        //当前记录的索引
        private long BUF_SIZE = 0;            ////缓存的最大数据个数
        private UInt32 m_dwReadStartPos = 0;    //buf的起始记录索引值
        private long m_dwCurCount = 0;        //pBuf中的记录总数
        private UInt64 m_i64RecordPosStart = 0;
        private UInt64 m_i64RecordPosEnd = 0;
        private Byte[] m_Buf;
        //************************************
        // Method:  OpenFile   [ public ]
        // Description:  以只读的方式打开文件,初始化线程相关信息
        // Returns [BOOL]: 打开成功
        // Parameters: 
        //    [ LPCTSTR lpszFileName ]: 文件名称路径 
        //    [ __int64 i64RecordPosStart ]: 记录的读取位置
        //    [ __int64 i64RecordPosEnd ]: 记录的结束位置
        //    [ size_t oneRecordSize ]: 一条记录的所占的字节大小
        // Author:   
        //************************************
        public bool OpenFile(string path, UInt64 i64RecordPosStart, UInt64 i64RecordPosEnd,UInt32 oneRecordSize)
        {
            m_file = new FileStream(path, FileMode.Open, FileAccess.Read);
            if (!m_file.CanRead)
                return false;

            m_dwRecordSize = oneRecordSize;
            SetBufSize(m_file.Length, oneRecordSize);   //计算 BUF_SIZE
            if (i64RecordPosEnd >= (UInt64)m_file.Length)
            {
                m_i64RecordPosEnd = (UInt64)m_file.Length - 1;
            }
            else
            {
                m_i64RecordPosEnd = i64RecordPosEnd;
            }

            m_i64RecordPosStart = i64RecordPosStart;
            m_dwRecordTotal = (UInt32)(m_i64RecordPosEnd - m_i64RecordPosStart + 1) / m_dwRecordSize;

            m_dwCurCount = m_dwRecordTotal;
            if (m_dwCurCount > BUF_SIZE)
            {
                m_dwCurCount = BUF_SIZE;
            }

            ReadBuf(0, m_dwCurCount);
            return true;
        }

        void SetBufSize(long dwBufMaxSize, UInt32 dwRecordSize)
        {
            UInt32 mb = 1024 * 1024;
            if (dwBufMaxSize <= mb*2)  // < 2M
            {
                //1M一下不需要 多级缓存
                BUF_SIZE = dwBufMaxSize / (long)dwRecordSize + 1;
            }
            else if (dwBufMaxSize <= mb * 20) // < MaxBufCount (M)
            {
                BUF_SIZE = mb / dwRecordSize + 1;   //采用 <= MaxBufCount 个buf
            }
            else
            {
                BUF_SIZE = (2* mb) / dwRecordSize + 1;
            }
        }

        public bool ReadBuf(long fromIndex, long count)
        {
            m_file.Seek((long)m_i64RecordPosStart + fromIndex * m_dwRecordSize, SeekOrigin.Begin);

            m_Buf = new Byte[count * m_dwRecordSize];
            m_file.Read(m_Buf, 0, m_Buf.Length);
            return true;
        }
        public bool FirstRecord(UInt32 dwFromIndex)
        {
            if (dwFromIndex > m_dwRecordTotal - 1)  //超过了最大记录索引
                return false;

            return true;
        }

        public BdfRecord GetCurRecord(UInt32 dwFromIndex)
        {
            if (dwFromIndex >= m_dwRecordTotal)
                return null;

            if (dwFromIndex < m_dwReadStartPos || dwFromIndex >= m_dwReadStartPos+ m_dwCurCount)
            {
                //当前Buf刷新
                long nSection = dwFromIndex / BUF_SIZE; //BUF_SIZE切出的第几段
                m_dwReadStartPos = (UInt32)(BUF_SIZE * nSection);
                long dwBufRecordCount = m_dwRecordTotal - m_dwReadStartPos;
                if (dwBufRecordCount > BUF_SIZE)
                    dwBufRecordCount = BUF_SIZE;

                ReadBuf(m_dwReadStartPos, dwBufRecordCount);
            }

            BdfRecord rd = new BdfRecord();
            Byte[] rdBuf = new byte[m_dwRecordSize];
            Array.Copy(m_Buf, m_dwRecordSize * (dwFromIndex - m_dwReadStartPos), rdBuf,0, rdBuf.Length);
            rd.SetParam(rdBuf);
            return rd;
        }
    }
}
